Limpieza y analisis de la base de datos Pollution

En este trabajo vamos a realizar un analisis y lipieza de la base de datos llamada Pollution que contiene datos sobre la contaminacion de cuatro gases diferentes en cada estado de EEUU desde 2000 hasta 2016

Limpieza

Esquema de trabajo:

  • Estraccion de datos a traves de la lectura del csv ‘pollution_us_2000_2016.csv’
  • Realizacion de una copia de la informacion para mantener la integriedad de los datos originales
  • Eliminar columnas que consideramos no relevantes en el analisis
  • Renombrar las columnas a nombres intuitivos y en castellano
  • Casting necesarios. Fecha como principal cambio
  • Creacion de una nueva columna producto de otras de la tabla

Antes de comenzar con el analisis vamos a importar las librerias necesarias:

library(dplyr)
## Warning: package 'dplyr' was built under R version 3.5.2
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
library(tidyr)
## Warning: package 'tidyr' was built under R version 3.5.2
library(lubridate)
## Warning: package 'lubridate' was built under R version 3.5.2
## 
## Attaching package: 'lubridate'
## The following object is masked from 'package:base':
## 
##     date
library(gdata)
## Warning: package 'gdata' was built under R version 3.5.2
## gdata: Unable to locate valid perl interpreter
## gdata: 
## gdata: read.xls() will be unable to read Excel XLS and XLSX files
## gdata: unless the 'perl=' argument is used to specify the location
## gdata: of a valid perl intrpreter.
## gdata: 
## gdata: (To avoid display of this message in the future, please
## gdata: ensure perl is installed and available on the executable
## gdata: search path.)
## gdata: Unable to load perl libaries needed by read.xls()
## gdata: to support 'XLX' (Excel 97-2004) files.
## 
## gdata: Unable to load perl libaries needed by read.xls()
## gdata: to support 'XLSX' (Excel 2007+) files.
## 
## gdata: Run the function 'installXLSXsupport()'
## gdata: to automatically download and install the perl
## gdata: libaries needed to support Excel XLS and XLSX formats.
## 
## Attaching package: 'gdata'
## The following objects are masked from 'package:dplyr':
## 
##     combine, first, last
## The following object is masked from 'package:stats':
## 
##     nobs
## The following object is masked from 'package:utils':
## 
##     object.size
## The following object is masked from 'package:base':
## 
##     startsWith
library(reshape2)
## Warning: package 'reshape2' was built under R version 3.5.2
## 
## Attaching package: 'reshape2'
## The following object is masked from 'package:tidyr':
## 
##     smiths

Lectura de los datos:

# Read in csv files
pollution <- read.csv("pollution_us_2000_2016.csv", stringsAsFactors = FALSE)
pollution <- read.csv("pollution_us_2000_2016.csv", header = T, sep=",")

Analisis inicial de la base de datos

Aqui veremos los tipos de datos, numero y nombre de filas y columnas, dimensiones, asi como el resumen estadistico de la base de datos

#como la base de datos es muy grande y tarda mucho en cargar, cogemos una muestra aleatoria de la bbdd
muestramia <- sample(1:nrow(pollution),size=10000,replace=FALSE)

pollutionmuestramia <- pollution[muestramia, ]
head(pollutionmuestramia)
dim(pollutionmuestramia)         # filas x columnas
## [1] 10000    29
head(pollutionmuestramia)       #bbdd aleatoria de pollution
summary(pollutionmuestramia)     #resumen de la bbdd pollution
##        X            State.Code     County.Code        Site.Num   
##  Min.   :    11   Min.   : 1.00   Min.   :  1.00   Min.   :   1  
##  1st Qu.: 26213   1st Qu.: 6.00   1st Qu.: 17.00   1st Qu.:   9  
##  Median : 53095   Median :17.00   Median : 59.00   Median :  69  
##  Mean   : 54764   Mean   :22.38   Mean   : 71.11   Mean   :1133  
##  3rd Qu.: 80066   3rd Qu.:40.00   3rd Qu.: 97.00   3rd Qu.:1100  
##  Max.   :134511   Max.   :80.00   Max.   :650.00   Max.   :9997  
##                                                                  
##                              Address              State     
##  PIKE AVE AT RIVER ROAD          : 201   California  :3276  
##  1130 EASTWAY DRIVE              : 199   Pennsylvania:1085  
##  128 S 'H' ST, LOMPOC            : 150   Texas       : 679  
##  5551 BETHEL ISLAND RD           : 145   New York    : 413  
##  14306 PARK AVE., VICTORVILLE, CA: 143   Arizona     : 398  
##  1630 N MAIN ST, LOS ANGELES     : 143   Illinois    : 298  
##  (Other)                         :9019   (Other)     :3851  
##            County                    City           Date.Local  
##  Los Angeles  : 535   Not in a city    : 797   2000-06-15:   8  
##  Santa Barbara: 484   New York         : 264   2006-06-13:   8  
##  Contra Costa : 480   Los Angeles      : 241   2008-06-15:   8  
##  San Diego    : 289   Phoenix          : 234   2012-06-23:   8  
##  Maricopa     : 278   North Little Rock: 201   2013-04-11:   8  
##  Orange       : 275   Charlotte        : 199   2014-04-13:   8  
##  (Other)      :7659   (Other)          :8064   (Other)   :9952  
##              NO2.Units        NO2.Mean       NO2.1st.Max.Value
##  Parts per billion:10000   Min.   :-0.5083   Min.   : -0.50   
##                            1st Qu.: 5.6852   1st Qu.: 13.00   
##                            Median :10.6957   Median : 23.70   
##                            Mean   :12.8467   Mean   : 25.34   
##                            3rd Qu.:17.7671   3rd Qu.: 36.00   
##                            Max.   :69.3043   Max.   :136.00   
##                                                               
##  NO2.1st.Max.Hour    NO2.AQI                    O3.Units    
##  Min.   : 0.00    Min.   :  0.00   Parts per million:10000  
##  1st Qu.: 5.00    1st Qu.: 12.00                            
##  Median : 9.00    Median : 22.00                            
##  Mean   :11.69    Mean   : 23.84                            
##  3rd Qu.:20.00    3rd Qu.: 34.00                            
##  Max.   :23.00    Max.   :108.00                            
##                                                             
##     O3.Mean        O3.1st.Max.Value  O3.1st.Max.Hour     O3.AQI      
##  Min.   :0.00000   Min.   :0.00000   Min.   : 0.00   Min.   :  0.00  
##  1st Qu.:0.01779   1st Qu.:0.02900   1st Qu.: 9.00   1st Qu.: 25.00  
##  Median :0.02583   Median :0.03800   Median :10.00   Median : 33.00  
##  Mean   :0.02610   Mean   :0.03921   Mean   :10.19   Mean   : 36.01  
##  3rd Qu.:0.03396   3rd Qu.:0.04900   3rd Qu.:11.00   3rd Qu.: 42.00  
##  Max.   :0.07717   Max.   :0.11500   Max.   :23.00   Max.   :200.00  
##                                                                      
##              SO2.Units        SO2.Mean       SO2.1st.Max.Value
##  Parts per billion:10000   Min.   :-1.5000   Min.   : -1.300  
##                            1st Qu.: 0.2609   1st Qu.:  0.900  
##                            Median : 1.0000   Median :  2.000  
##                            Mean   : 1.9240   Mean   :  4.608  
##                            3rd Qu.: 2.3333   3rd Qu.:  5.000  
##                            Max.   :56.0375   Max.   :164.000  
##                                                               
##  SO2.1st.Max.Hour    SO2.AQI                     CO.Units    
##  Min.   : 0.000   Min.   :  0.000   Parts per million:10000  
##  1st Qu.: 4.000   1st Qu.:  1.000                            
##  Median : 8.000   Median :  3.000                            
##  Mean   : 9.542   Mean   :  7.208                            
##  3rd Qu.:14.000   3rd Qu.:  9.000                            
##  Max.   :23.000   Max.   :141.000                            
##                   NA's   :4907                               
##     CO.Mean        CO.1st.Max.Value  CO.1st.Max.Hour      CO.AQI      
##  Min.   :-0.3000   Min.   :-0.2000   Min.   : 0.000   Min.   : 0.000  
##  1st Qu.: 0.1855   1st Qu.: 0.3000   1st Qu.: 0.000   1st Qu.: 2.000  
##  Median : 0.2957   Median : 0.4000   Median : 6.000   Median : 5.000  
##  Mean   : 0.3680   Mean   : 0.6176   Mean   : 7.863   Mean   : 6.006  
##  3rd Qu.: 0.4708   3rd Qu.: 0.7913   3rd Qu.:13.000   3rd Qu.: 8.000  
##  Max.   : 3.3652   Max.   : 9.2000   Max.   :23.000   Max.   :73.000  
##                                                       NA's   :4953
head(pollutionmuestramia, 10)    # primeras diez filas
tail(pollutionmuestramia, 10)    #ultimas diez filas
class(pollutionmuestramia)   #tipo 
## [1] "data.frame"
nrow(pollutionmuestramia)    # número de filas
## [1] 10000
ncol(pollutionmuestramia)    # número de columnas
## [1] 29

Transformacion de los datos a DataFrame

#convertimos a dataframe
pollutionmuestramia <- as.data.frame(pollutionmuestramia)
#como vemos con str el tipo de cada variables esta bien no hay que transformar
str(pollutionmuestramia)     #las filas son oobservaciones y columnas las variables
## 'data.frame':    10000 obs. of  29 variables:
##  $ X                : int  88230 54066 85364 77134 7454 51812 109889 21401 93426 68878 ...
##  $ State.Code       : int  42 34 36 24 6 11 42 6 37 36 ...
##  $ County.Code      : int  11 7 81 33 13 1 125 59 183 81 ...
##  $ Site.Num         : int  11 3 124 30 2 41 5 1003 14 124 ...
##  $ Address          : Factor w/ 204 levels "          6100 ARLINGTON BLVD MONTG WARD",..: 10 148 188 165 68 95 146 65 91 188 ...
##  $ State            : Factor w/ 47 levels "Alabama","Alaska",..: 37 29 31 22 5 10 37 5 32 31 ...
##  $ County           : Factor w/ 133 levels "Ada","Adair",..: 13 22 99 96 27 36 128 91 127 99 ...
##  $ City             : Factor w/ 144 levels "Albuquerque",..: 93 25 88 12 35 136 27 37 105 88 ...
##  $ Date.Local       : Factor w/ 5996 levels "2000-01-01","2000-01-02",..: 3196 1569 4022 5045 2548 4721 4221 3433 5806 3656 ...
##  $ NO2.Units        : Factor w/ 1 level "Parts per billion": 1 1 1 1 1 1 1 1 1 1 ...
##  $ NO2.Mean         : num  9.21 18.46 39.05 9.43 16 ...
##  $ NO2.1st.Max.Value: num  16 31 47.2 18.1 29 50 20 4 30.2 22 ...
##  $ NO2.1st.Max.Hour : int  9 19 9 10 18 9 16 7 18 19 ...
##  $ NO2.AQI          : int  15 29 44 17 27 47 19 4 28 21 ...
##  $ O3.Units         : Factor w/ 1 level "Parts per million": 1 1 1 1 1 1 1 1 1 1 ...
##  $ O3.Mean          : num  0.01837 0.04146 0.00375 0.01704 0.01087 ...
##  $ O3.1st.Max.Value : num  0.037 0.055 0.009 0.025 0.023 0.015 0.047 0.052 0.036 0.023 ...
##  $ O3.1st.Max.Hour  : int  12 14 8 12 9 9 8 9 9 6 ...
##  $ O3.AQI           : int  31 47 8 21 19 13 40 44 33 19 ...
##  $ SO2.Units        : Factor w/ 1 level "Parts per billion": 1 1 1 1 1 1 1 1 1 1 ...
##  $ SO2.Mean         : num  6.05 8.6 11.754 1.271 0.818 ...
##  $ SO2.1st.Max.Value: num  10.3 14.3 19.5 2.6 4 4 7 1 2.8 7.2 ...
##  $ SO2.1st.Max.Hour : int  11 11 8 11 15 12 7 5 23 20 ...
##  $ SO2.AQI          : num  NA NA 27 NA 6 6 10 1 NA NA ...
##  $ CO.Units         : Factor w/ 1 level "Parts per million": 1 1 1 1 1 1 1 1 1 1 ...
##  $ CO.Mean          : num  0 0.521 0.443 0.175 0.596 ...
##  $ CO.1st.Max.Value : num  0 0.6 0.706 0.26 1.3 ...
##  $ CO.1st.Max.Hour  : int  0 19 9 9 22 22 5 8 23 0 ...
##  $ CO.AQI           : num  0 7 NA NA NA NA 8 1 NA 2 ...

Una vez tenemos analizada la vista inicial dela tabla vamos a comenzar con la limpieza. En este caso lo realizaremos sobre columnas. Viendo el nombre de las mismas, eliminando las sobrantes, cambiando el nombre de todas ellas y por ultimo seprando la fecha creando tres diferentes con los datos del dia, el mes y el año

names(pollutionmuestramia)     #nombre de las columnas 
##  [1] "X"                 "State.Code"        "County.Code"      
##  [4] "Site.Num"          "Address"           "State"            
##  [7] "County"            "City"              "Date.Local"       
## [10] "NO2.Units"         "NO2.Mean"          "NO2.1st.Max.Value"
## [13] "NO2.1st.Max.Hour"  "NO2.AQI"           "O3.Units"         
## [16] "O3.Mean"           "O3.1st.Max.Value"  "O3.1st.Max.Hour"  
## [19] "O3.AQI"            "SO2.Units"         "SO2.Mean"         
## [22] "SO2.1st.Max.Value" "SO2.1st.Max.Hour"  "SO2.AQI"          
## [25] "CO.Units"          "CO.Mean"           "CO.1st.Max.Value" 
## [28] "CO.1st.Max.Hour"   "CO.AQI"
colnames(pollutionmuestramia)  #nombre de las columnas
##  [1] "X"                 "State.Code"        "County.Code"      
##  [4] "Site.Num"          "Address"           "State"            
##  [7] "County"            "City"              "Date.Local"       
## [10] "NO2.Units"         "NO2.Mean"          "NO2.1st.Max.Value"
## [13] "NO2.1st.Max.Hour"  "NO2.AQI"           "O3.Units"         
## [16] "O3.Mean"           "O3.1st.Max.Value"  "O3.1st.Max.Hour"  
## [19] "O3.AQI"            "SO2.Units"         "SO2.Mean"         
## [22] "SO2.1st.Max.Value" "SO2.1st.Max.Hour"  "SO2.AQI"          
## [25] "CO.Units"          "CO.Mean"           "CO.1st.Max.Value" 
## [28] "CO.1st.Max.Hour"   "CO.AQI"
#pasamos los nombres de las variables a minusculas
names(pollutionmuestramia) <- tolower(names(pollutionmuestramia))

#separamos la fecha en la columna date local, y la divido en 3 columnas distintas: en año, mes y dia, ahora tenemos 31 variables en vez de 29
pollutionmuestramia <- separate(pollutionmuestramia, date.local, c("year", "month", "day")) 

pollutionmuestramia$x <- NULL   #asigno NULL al valor del area, es decir borror la primera columna que no es interesante
pollutionmuestramia
#cambiamos el nombre de las variables 
colnames(pollutionmuestramia) <- c("codigo_estado", "codigo_condado", "numero_sitio", "direccion", "estado", "condado", "ciudad",
                           "ano", "mes", "dia","unidades_NO2", "media_NO2", "valor_max_1st_NO2", "hora_max_1st_NO2",
                           "AQI_NO2", "unidades_O3", "media_O3", "valor_max_1st_O3", "hora_max_1st_O3",
                           "AQI_O3", "unidades_SO2", "media_SO2", "valor_max_1st_SO2", "hora_max_1st_SO2",
                           "AQI_SO2", "unidades_CO", "media_CO", "valor_max_st_CO", "hora_max_1st_CO",
                           "AQI_CO")
pollutionmuestramia
#ponemos en minuscula el contenido de la variable direccion
pollutionmuestramia$direccion <- tolower(pollutionmuestramia$direccion)
pollutionmuestramia
#creamos una nueva columna que sea la media de la suma de los 4 gases
pollutionmuestramia$valoresmaximos <- (pollutionmuestramia$valor_max_1st_NO2 + pollutionmuestramia$valor_max_1st_O3 + 
                                         pollutionmuestramia$valor_max_1st_SO2 + pollutionmuestramia$valor_max_st_CO)
pollutionmuestramia

Filas

Al tener ya limpias las columnas podemos centrarnos en las filas. Verificaremos si existen valores nulos o NaN y los corregiremos, asi como saber las filas que tienen los datos correctos

#check Nas values
head(is.na(pollutionmuestramia), 1)
##        codigo_estado codigo_condado numero_sitio direccion estado condado
## 832914         FALSE          FALSE        FALSE     FALSE  FALSE   FALSE
##        ciudad   ano   mes   dia unidades_NO2 media_NO2 valor_max_1st_NO2
## 832914  FALSE FALSE FALSE FALSE        FALSE     FALSE             FALSE
##        hora_max_1st_NO2 AQI_NO2 unidades_O3 media_O3 valor_max_1st_O3
## 832914            FALSE   FALSE       FALSE    FALSE            FALSE
##        hora_max_1st_O3 AQI_O3 unidades_SO2 media_SO2 valor_max_1st_SO2
## 832914           FALSE  FALSE        FALSE     FALSE             FALSE
##        hora_max_1st_SO2 AQI_SO2 unidades_CO media_CO valor_max_st_CO
## 832914            FALSE    TRUE       FALSE    FALSE           FALSE
##        hora_max_1st_CO AQI_CO valoresmaximos
## 832914           FALSE  FALSE          FALSE
#preguntamos si hay alguno
head(any(is.na(pollutionmuestramia)), 1)
## [1] TRUE
#contamos el numero de Nas
sum(is.na(pollutionmuestramia))
## [1] 9860
#encontrar las filas que no falten datos
head(complete.cases(pollutionmuestramia), 30)
##  [1] FALSE FALSE FALSE FALSE FALSE FALSE  TRUE  TRUE FALSE FALSE FALSE
## [12] FALSE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE  TRUE FALSE FALSE
## [23] FALSE  TRUE  TRUE FALSE FALSE FALSE FALSE FALSE
#subset data solo con los casos completos
head(pollutionmuestramia[complete.cases(pollutionmuestramia),])

Realizacion de los graficos

Histogramas

Para poder ver las distribuciones de cada variable

histogramas de los datos de NO2

hist(pollutionmuestramia$media_NO2, main = "Histograma Media NO2", xlab = "media")

La media de NO2 parece seguir una distribución similar a la de Poisson con una cola larga a la derecha. La mayoría de los estados tienen una media similar que se encuentra entre 5 y 20, sin embargo, hay ciertos estados que salen de esa media. California o Pennsylvania son los más representativos y son los que generan, en parte, esa cola lateral alargada.

hist(pollutionmuestramia$valor_max_1st_NO2, main = "Histograma Valor Máximo NO2", xlab = "valores máximo")

Los valores máximos se concentran en valores más pequeños en su mayoría, generando una distribución, de nuevo, similar a Poisson, aunque con una cola derecha más corta, ya que hay pocos datos que se vayan lejos de la media.

hist(pollutionmuestramia$hora_max_1st_NO2, main = "Histograma Hora Máximas NO2", xlab = "horas máximas")

Parece observarse una curva en forma de U en el histograma en el que hay valores altos durante la noche y tarde y muy bajos durante la mañana, hasta el mediodía. Ligera excepción de madrugada, con orígenes desconocidos. Quizás incluso una mala medición.

hist(pollutionmuestramia$AQI_NO2, main = "Histograma AQI NO2", xlab = "AQI")

Al igual que ocurre con la media de NO2, el AQI de NO2 vuelve a parecer una distribución de Poisson muy pegada a la izquierda, con la mayoría de valores muy bajos y, por lo tanto, la media también.

En cambio, la cola derecha, a pesar de ser pequeña, es larga. Lo que significa que hay ciertos estados que tienen una gran diferencia, incluso entre ellos mismos.

Histogramas de los datos de la media de los demas gases

hist(pollutionmuestramia$media_O3, main = "Histograma Media O3", xlab = "media")

En el caso del ozono, sin embargo, la distribución se parece mas a una normal, sin embargo, existen ligeras asimetrías. Puede ser debido, sobre todo, al amplio número de estados a medir.

hist(pollutionmuestramia$media_SO2, main = "Histograma Media SO2", xlab = "media")

hist(pollutionmuestramia$media_CO, main = "Histograma Media CO", xlab = "media")

En el caso del SO2 y el CO, la distribución es más pronunciada y semejante a Poisson. En este caso, la mayoría vuelven a encontrarse de media en la zona más baja, sin embargo, con un pico muy alto. Se debe probablemente a la existencia de numerosos puntos atípicos que desvirtúan en parte la distribución.

Boxplots

#boxolot de los datos de Media 03 a lo largo de los años
boxplot(media_O3 ~ ano, data=pollutionmuestramia, main="Media 03 / Años", xlab="Años", ylab="Media O3")

No parece haber muchas variaciones a lo largo de los años, al menos, respecto a la media. Sin embargo, hay años en los que determinados estados salen fuera de la misma, situándose como puntos atípicos, lo que provoca un desplazamiento de la media.

#boxolot de los datos de Media 03 en los diferentes estados
boxplot(media_O3 ~ estado, data=pollutionmuestramia, main="Media 03 / Estados", xlab="Estados", ylab="Media O3")

Sin embargo, sí se pueden observar diferencias significativas entre las medias de los diferentes estados, viendo cómo algunos tienen una media muy baja, media o muy alta. Aunque sí que existe una tendencia de medias a estar entre dos valores próximos (Entre 0,2 y 0,3).